<?php
/** dzEvent
 *
 *  Implements a event handler class that handles the events the user
 *  causes. Dataxi manager state machine calls this when it receives
 *  an event from the user.
 *
 *
 *  This code is licensed under GPL2.
 *  See LICENSE or www.gnu.org for more details.
 *
 *  @auhor Henri Ranki
 *
 *  $Id: dzevent.php 595 2006-04-03 16:00:47Z jyry $
 */


include_once("sodebug.php");
include_once("dzsmconst.php");
include_once("dzgeneric.php");
include_once("dzkeycodes.php");
include_once("dzconst.php");
include_once("dztemplate.php");
include_once("dzerror.php");
include_once("dzrpc.php");
include_once("sogeneric.php");

/** Data structure for delivering the result from the event handler
 *  @var ? $Status;
 *  @var ? $NextState
 */
class dzEventResult {
    var $Status;
    var $NextState;
}; // dzEventResult


/** Event handler result codes */
define("DZE_ERROR", 0);
define("DZE_OK", 1);
define("DZE_NOT_DEFINED", 1);


/** Define basic stonga events. */
define("DZE_COMMIT", 1);
$ECommit = array(DZ_STATE_FROM_QUERY_LOOP => DZ_STATE_COMMIT_PSEUDO_FORM,
                 DZ_STATE_FROM_EDIT_LOOP => DZ_STATE_COMMIT_EDIT,
                 DZ_STATE_FROM_NEW_LOOP => DZ_STATE_COMMIT_EDIT,
                 DZ_STATE_FROM_BROWSE => DZ_STATE_TO_PARENT_VIEW,
                 DZ_STATE_FROM_SUB_VIEW => DZ_STATE_TO_PARENT_VIEW);

define("DZE_ROLLBACK", 2);
$ERollback = array(DZ_STATE_FROM_QUERY_LOOP => DZ_STATE_KILL_VIEW,
                   DZ_STATE_FROM_EDIT_LOOP => DZ_STATE_CANCEL_EDIT,
                   DZ_STATE_FROM_NEW_LOOP => DZ_STATE_CANCEL_EDIT,
                   DZ_STATE_FROM_BROWSE => DZ_STATE_RETURN_QUERYING,
                   DZ_STATE_FROM_PICK_UP => DZ_STATE_UNDEFINED,
                   DZ_STATE_FROM_SUB_VIEW => DZ_STATE_TO_PARENT_VIEW);

define("DZE_PREVIOUS", 3);
$EPrevious = array(DZ_STATE_FROM_BROWSE => DZ_STATE_BROWSE_PREVIOUS);

define("DZE_NEXT", 4);
$ENext = array(DZ_STATE_FROM_BROWSE => DZ_STATE_BROWSE_NEXT);

define("DZE_LIST", 5);
$EList = array(DZ_STATE_FROM_BROWSE => DZ_STATE_CHANGE_BROWSE_MODE);

define("DZE_EDIT", 6);
$EEdit = array(DZ_STATE_FROM_BROWSE => DZ_STATE_START_EDIT);

define("DZE_NEW", 7);
$ENew = array(DZ_STATE_FROM_QUERY_LOOP => DZ_STATE_START_NEW,
              DZ_STATE_FROM_BROWSE => DZ_STATE_START_NEW);

define("DZE_DELETE", 8);
$EDelete = array(DZ_STATE_FROM_BROWSE => DZ_STATE_DEL_ROW);

define("DZE_ORDER_BY", 9);
$EOrderBy = array(DZ_STATE_FROM_QUERY_LOOP => DZ_STATE_CHANGE_ORDER);

define("DZE_CHANGE_VIEW", 10);
$EChangeView = array(DZ_STATE_FROM_INITIAL => DZ_STATE_CHANGE_VIEW,
                     DZ_STATE_FROM_QUERY_LOOP => DZ_STATE_CHANGE_VIEW,
                     DZ_STATE_FROM_EDIT_LOOP => DZ_STATE_CHANGE_VIEW,
                     DZ_STATE_FROM_NEW_LOOP => DZ_STATE_CHANGE_VIEW,
                     DZ_STATE_FROM_BROWSE => DZ_STATE_CHANGE_VIEW,
                     DZ_STATE_FROM_SUB_VIEW => DZ_STATE_CHANGE_VIEW);

define("DZE_NEW_VIEW", 11);
$ENewView = array(DZ_STATE_FROM_INITIAL => DZ_STATE_ADD_VIEW,
                 DZ_STATE_FROM_QUERY_LOOP => DZ_STATE_ADD_VIEW,
                 DZ_STATE_FROM_EDIT_LOOP => DZ_STATE_ADD_VIEW,
                 DZ_STATE_FROM_NEW_LOOP => DZ_STATE_ADD_VIEW,
                 DZ_STATE_FROM_BROWSE => DZ_STATE_ADD_VIEW,
                 DZ_STATE_FROM_PICK_UP => DZ_STATE_ADD_VIEW,
                 DZ_STATE_FROM_SUB_VIEW => DZ_STATE_ADD_VIEW);

define("DZE_EXIT", 12);
$EExit = array(DZ_STATE_FROM_INITIAL => DZ_STATE_TERMINATE_SESSION,
              DZ_STATE_FROM_QUERY_LOOP => DZ_STATE_TERMINATE_SESSION,
              DZ_STATE_FROM_EDIT_LOOP => DZ_STATE_TERMINATE_SESSION,
              DZ_STATE_FROM_NEW_LOOP => DZ_STATE_TERMINATE_SESSION,
              DZ_STATE_FROM_BROWSE => DZ_STATE_TERMINATE_SESSION,
              DZ_STATE_FROM_PICK_UP => DZ_STATE_TERMINATE_SESSION,
              DZ_STATE_FROM_SUB_VIEW => DZ_STATE_TERMINATE_SESSION);

define("DZE_HELP", 13);
$EHelp = array(DZ_STATE_FROM_QUERY_LOOP => DZ_STATE_SHOW_HELP,
              DZ_STATE_FROM_EDIT_LOOP => DZ_STATE_SHOW_HELP,
              DZ_STATE_FROM_NEW_LOOP => DZ_STATE_SHOW_HELP,
              DZ_STATE_FROM_BROWSE => DZ_STATE_SHOW_HELP,
              DZ_STATE_FROM_PICK_UP => DZ_STATE_SHOW_HELP);

define("DZE_INS_LINE", 14);
$EInsLine = array(DZ_STATE_FROM_EDIT_LOOP => DZ_STATE_INSERT_LINE,
                  DZ_STATE_FROM_NEW_LOOP => DZ_STATE_INSERT_LINE);

define("DZE_DEL_LINE", 15);
$EDelLine = array(DZ_STATE_FROM_EDIT_LOOP => DZ_STATE_DEL_LINE,
                  DZ_STATE_FROM_NEW_LOOP => DZ_STATE_DEL_LINE);


define("DZE_PICK_UP", 16);
$EPick = array(DZ_STATE_FROM_EDIT_LOOP => DZ_STATE_START_PICK_UP,
               DZ_STATE_FROM_QUERY_LOOP => DZ_STATE_START_PICK_UP,
               DZ_STATE_FROM_NEW_LOOP => DZ_STATE_START_PICK_UP);

define("DZE_KILLVIEW", 17);
$EKillView = array(DZ_STATE_FROM_QUERY_LOOP => DZ_STATE_KILL_VIEW,
                   DZ_STATE_FROM_EDIT_LOOP => DZ_STATE_KILL_VIEW,
                   DZ_STATE_FROM_NEW_LOOP => DZ_STATE_KILL_VIEW,
                   DZ_STATE_FROM_BROWSE => DZ_STATE_KILL_VIEW,
                   DZ_STATE_FROM_PICK_UP => DZ_STATE_KILL_VIEW,
                   DZ_STATE_FROM_SUB_VIEW => DZ_STATE_KILL_VIEW);

define("DZE_SUSPEND", 18);
$ESuspend = array(DZ_STATE_FROM_QUERY_LOOP => DZ_STATE_SUSPEND,
                   DZ_STATE_FROM_EDIT_LOOP => DZ_STATE_SUSPEND,
                   DZ_STATE_FROM_NEW_LOOP => DZ_STATE_SUSPEND,
                   DZ_STATE_FROM_BROWSE => DZ_STATE_SUSPEND,
                   DZ_STATE_FROM_PICK_UP => DZ_STATE_SUSPEND,
                   DZ_STATE_FROM_INITIAL => DZ_STATE_SUSPEND,
                   DZ_STATE_FROM_SUB_VIEW => DZ_STATE_SUSPEND);

/** Event handler class. Decides to which state to move.
 *  @var array $__EventStruct Information on allowed events and to which
 *      states they apply.
 *  @var soSet/array $__KeyMap Structure that maps key presses to state transfers
 *  @var dzSession $__SesData Reference to session information
 */
class dzEvent {
    /** @access private */
    var $__EventStruct;
    var $__KeyMap;
    var $__SesData;


    /** constructor
     *  @param dzSession $SesData Reference to session data
     */
    function dzEvent(&$SesData) {
        global $ECommit, $ERollback, $EPrevious, $ENext, $EEdit, $ENew,
               $EDelete, $EOrderBy, $EChangeView, $ENewView, $EExit, $EHelp,
               $EPick, $EList, $EKillView, $ESuspend;

        $this->__SesData = &$SesData;

        /* Construct the event structure */
        $this->__EventStruct[DZSE_COMMIT] = new soSet();
        $this->__EventStruct[DZSE_COMMIT]->joinArray($ECommit);

        $this->__EventStruct[DZSE_ROLLBACK] = new soSet();
        $this->__EventStruct[DZSE_ROLLBACK]->joinArray($ERollback);

        $this->__EventStruct[DZSE_PREVIOUS] = new soSet();
        $this->__EventStruct[DZSE_PREVIOUS]->joinArray($EPrevious);

        $this->__EventStruct[DZSE_NEXT] = new soSet();
        $this->__EventStruct[DZSE_NEXT]->joinArray($ENext);

        $this->__EventStruct[DZSE_LISTBROWSE] = new soSet();
        $this->__EventStruct[DZSE_LISTBROWSE]->joinArray($EList);

        $this->__EventStruct[DZSE_EDIT] = new soSet();
        $this->__EventStruct[DZSE_EDIT]->joinArray($EEdit);

        $this->__EventStruct[DZSE_NEW] = new soSet();
        $this->__EventStruct[DZSE_NEW]->joinArray($ENew);

        $this->__EventStruct[DZSE_DELETE] = new soSet();
        $this->__EventStruct[DZSE_DELETE]->joinArray($EDelete);

        $this->__EventStruct[DZSE_ORDERBY] = new soSet();
        $this->__EventStruct[DZSE_ORDERBY]->joinArray($EOrderBy);

        $this->__EventStruct[DZSE_CHANGEVIEW] = new soSet();
        $this->__EventStruct[DZSE_CHANGEVIEW]->joinArray($EChangeView);

        $this->__EventStruct[DZSE_NEWVIEW] = new soSet();
        $this->__EventStruct[DZSE_NEWVIEW]->joinArray($ENewView);

        $this->__EventStruct[DZSE_EXIT] = new soSet();
        $this->__EventStruct[DZSE_EXIT]->joinArray($EExit);

        $this->__EventStruct[DZSE_HELP] = new soSet();
        $this->__EventStruct[DZSE_HELP]->joinArray($EHelp);

        $this->__EventStruct[DZSE_KILLVIEW] = new soSet();
        $this->__EventStruct[DZSE_KILLVIEW]->joinArray($EKillView);

        $this->__EventStruct[DZSE_SUSPEND] = new soSet();
        $this->__EventStruct[DZSE_SUSPEND]->joinArray($ESuspend);

        /* initialize the keymap structure */
        $this->createKeyMap();
    } // Constructor


    /** Fill in the keymap structure according to the defines in site.ini-file.
     *  If key is not defined a default value is used. Default key map is as
     *  follows:
     *  ok = c-enter
     *  cancel = c-c
     *  del_line = c-del
     *  inc_line = c-ins
     *  browse_next = c-right
     *  browse_prev = c-left
     *  pick_up = c-l
     */
    function createKeyMap() {

        /* Introduce global key code table a<nd transfer tables */
        global $_DZ_GLOBALS;
        global $ECommit, $ERollback, $EPrevious, $ENext, $EEdit, $ENew,
               $EDelete, $EOrderBy, $EChangeView, $ENewView, $EExit, $EHelp,
               $EInsLine, $EDelLine, $EPick, $EKillView, $ESuspend;

        $keyMap = new soSet();
        $ini = dzGetIni("app");
        $dx_ini = dzGetIni("dataxi");
        if ($dx_ini == null) {
            dzSysError("Could not find dataxi.ini. It should be in ".
                       "the dataxi directory.");
        } // if

        /* If application ini not found at all get the defaults from
         *  the dataxi.ini */
        if ($ini == null) $ini = dx_ini;

        /* Start intitalizing key map structure. */
        $key = $ini->getValue("keymap", "ok", SOINI_NOSUB);
        if (!$key) {
            $key = $dx_ini->getValue("keymap", "ok", SOINI_NOSUB);
            if (!$key) $key = "c-enter";
        }; // if
        $keyMap->setItem($_DZ_GLOBALS[DZGV_KEYCODES][$key], $ECommit);

        $key = $ini->getValue("keymap", "cancel", SOINI_NOSUB);
        if (!$key) {
            $key = $dx_ini->getValue("keymap", "cancel", SOINI_NOSUB);
            if (!$key) $key = "c-bs";
        }; // if
        $keyMap->setItem($_DZ_GLOBALS[DZGV_KEYCODES][$key], $ERollback);

        $key = $ini->getValue("keymap", "del_line". SOINI_NOSUB);
        if (!$key) {
            $key = $dx_ini->getValue("keymap", "del_line", SOINI_NOSUB);
            if (!$key) $key = "c-del";
        }; // if
        $keyMap->setItem($_DZ_GLOBALS[DZGV_KEYCODES][$key], $EDelLine);

        $key = $ini->getValue("keymap", "ins_line", SOINI_NOSUB);
        if (!$key) {
            $key = $dx_ini->getValue("keymap", "ins_line", SOINI_NOSUB);
            if (!$key) $key = "c-ins";
        }; // if
        $keyMap->setItem($_DZ_GLOBALS[DZGV_KEYCODES][$key], $EInsLine);

        $key = $ini->getValue("keymap", "browse_next", SOINI_NOSUB);
        if (!$key) {
            $key = $dx_ini->getValue("keymap", "browse_next", SOINI_NOSUB);
            if ($key) $key = "c-right";
        }; // if
        $keyMap->setItem($_DZ_GLOBALS[DZGV_KEYCODES][$key], $ENext);

        $key = $ini->getValue("keymap", "browse_prev", SOINI_NOSUB);
        if (!$key) {
            $key = $dx_ini->getValue("keymap", "browse_prev", SOINI_NOSUB);
            if (!$key) $key = "c-left";
        }; // if
        $keyMap->setItem($_DZ_GLOBALS[DZGV_KEYCODES][$key], $EPrev);

        $key = $ini->getValue("keymap", "pick", SOINI_NOSUB);
        if (!$key) {
            $key = $dx_ini->getValue("keymap", "pick", SOINI_NOSUB);
            if (!$key) $key = "c-l";
        }; // if
        $keyMap->setItem($_DZ_GLOBALS[DZGV_KEYCODES][$key], $EPick);

        $this->__KeyMap = $keyMap;
    } // createKeyMap


    /** Process the event occurred at client side.
     *  @return dzEventResult Next state and status
     */
    function processEvents() {
        $result = new dzEventResult;
        $template = &$this->__SesData->HotView->Template;
        $event = $template->WidgetData->getItem(DZRI_EVENT);
        switch ($template->WidgetData->getItem(DZRI_FRAME)) {
            case "menu":
            case "stonga":
                $result = $this->stongaEvent($this->__SesData);
                break;

            case "subari":
                $result = $this->subariEvent($this->__SesData);
                break;

            case "nalle":
                if ($event == "EKeyboard") {
                    $result = $this->keyPressedEvent($this->__SesData);
                } else if ($event == "ENewLine") {
                    $result->NextState = DZ_STATE_ADD_LINE;
                    $result->Status = DZE_OK;
                } else if ($event == "EList") {
                    $result->NextState = DZ_STATE_JUMP_TO_BROWSE_POS;
                    $result->Status = DZE_OK;
                } else if ($event == "EIrpc") {
                    /* Return the focus there where we left */
                    $widget = $template->WidgetData->getItem(DZRI_WIDGET);
                    $template->addInitAction(DZIA_SET_FOCUS, $widget);

                    $rpc_def = $template->WidgetData->getItem(DZRI_OPTIONS);

                    /* Call the remote procedure */
                    if (!doSubariRpc($rpc_def, $this->__SesData)) {
                        $e_msg = new dzErrorMsg(DZER_RPC_SUBARI_FAILED,
                                                "Nalle",
                                                DZERT_SYSTEM, DZERL_ERROR);
                        $this->__SesData->ErrorLog->add($e_msg);
                    } // if $this->doSubariMsg

                    $result->NextState = DZ_STATE_RECOVER_ERROR;
                    $result->Status = DZE_OK;
                } else if ($event == "EFilterChange") {
                    /* Return the focus there where we left */
                    $template->addInitAction(
                                DZIA_SET_FOCUS,
                                $template->WidgetData->getItem(DZRI_WIDGET));

                    /* Set the information on row that caused the filter
                       change event */
                    $info = $this->__SesData->FocusGroup."_".
                            $this->__SesData->FocusRow;
                    $template->addInitAction(DZIA_SET_LAST_FILTER, $info);
                    /* Purkki and the current row is already updated.
                      We need just reconstruct the code. */
                    $result->NextState = DZ_STATE_RECOVER_ERROR;
                    $result->Status = DZE_OK;
                } else if ($event == "EValidate") {
                    $result->NextState = DZ_STATE_VALIDATE_FIELD;
                    $result->Status = DZE_OK;
                } else if ($event == "EFetch") {
                    $result->NextState = DZ_STATE_UPD_FETCH_FIELD;
                    $result->Status = DZE_OK;
                } else if ($event == "EChangePage") {
                    $result->NextState = DZ_STATE_CHANGE_PAGE;
                    $result->Status = DZE_OK;
                } else {
                    $result->NextState = DZ_STATE_GO_INITIAL;
                    $result->Status = DZE_ERROR;
                }
                break;

            default:
                $result->NextState = DZ_STATE_GO_INITIAL;
                $result->Status = DZE_OK;
        }

        return $result;
    } // processEvents


    /** Process the stonga and menu events.
     *  @param dzEventResult The next state to move and status
     */
    function stongaEvent() {
        $result = new dzEventResult;
        $template = &$this->__SesData->HotView->Template;
        $event = $template->WidgetData->getItem(DZRI_EVENT);
        $stateSet = $this->__EventStruct[$event];
        if (is_object($stateSet)) {
            $enter_state = $template->getViewData(DZ_VI_ENTER_STATE);
            $result->NextState = $stateSet->getItem($enter_state);
            $result->Status = DZE_OK;
            soDebug("dzEvent->stongaEvent: ".$event.", next state=".
                    $result->NextState, SOD_DET);
        } else {
            soDebug("dzEvent->stongaEvent: ".$event, SOD_DET);
            $result->NextState = DZ_STATE_GO_INITIAL;
            $result->Status = DZE_ERROR;
        } // if

        return $result;
    } // stongaEvent


    /** Handles the key event that occurred at the client side
     *  @param dzEventResult The next state to move and status
     */
    function keyPressedEvent() {
        $widget_data = &$this->__SesData->HotView->Template->WidgetData;
        $result = new dzEventResult;

        $key_code = $widget_data->getItem(DZRI_OPTIONS);
        /* The following is gludge. But life without gludges is too boring.
           This gludge is due to textarea widget that sends c-enter event
           with different key code (2+13) instead of 2+65293 that is sent by
           other widgets */
        if ($key_code == "2+13") $key_code = "2+65293";

        soDebug("dzEvent->keyPressedEvent: Key code = ".$key_code, SOD_DET);

        /* Return the focus there where we left */
        $widget = $widget_data->getItem(DZRI_WIDGET);

        /* Was the event caused by real widget. Not a button
           emulating a kaypress */
        if (soSubStr($widget, 0, 4) != "fake") {
            $this->__SesData->HotView->Template->addInitAction(DZIA_SET_FOCUS,
                                                               $widget);
        } // if $widget

        $state_map = $this->__KeyMap->getItem($key_code);
        if ($this->__KeyMap->Error) {
            $result->Status = DZE_NOT_DEFINED;
            $result->NextState = DZ_STATE_RECOVER_ERROR;
            return $result;  // <-- Exit!
        }
        $result->Status = DZE_OK;
        $enter_state = $this->__SesData->HotView->Template->getViewData(
                                                        DZ_VI_ENTER_STATE);
        $result->NextState = $state_map[$enter_state];
        /* Confirm that key code applied to this view mode */
        if ($result->NextState == 0) {
            $result->NextState = DZ_STATE_RECOVER_ERROR;
        }; // if

        return $result;
    } // keyPressedEvent


    /** Process Subari events.
     *  @param dzEventResult The next state to move and status
     */
    function subariEvent() {
        $template = &$this->__SesData->HotView->Template;
        $options = $template->WidgetData->getItem(DZRI_OPTIONS);
        $item = $template->Subari->getItem($options);
        return handleSubariEventItem($item, $this->__SesData);
    } // subariEvent

} //dzEvent


/** Handles subari event.
 *  This is a separate function because it is used in together with form
 *  pre/post events as well.
 *  @param soSet $Item Subari event information
 *  @param dzSession $SesData Current session data
 *  @return object dzEventResult Event result.
 */
function handleSubariEventItem($Item, &$SesData) {

    /* Parse the action to perform and the source stream for it. */
    $action = dzParseMenuTarget($Item->getItem(DZS_EXE));

    soDebug("dzEvent/handleSubariEventItem: subari action=".
            $action->Target, SOD_DET);

    $result = new dzEventResult();
    switch ($action->Target) {
        case DZMT_NALLE:
            /* This is normal dataxi view, except that it is a sub view.
             * Thus no new item will appear in the view list. */
            $form_src = $action->Stream;
            /* Add the path */
            $form_folder = dzGetIniPath(DZID_FORM_SOURCE_FOLDER);
            $form_src = soSwapStr($form_src, "://", "://".
                                  $form_folder."/", 1);

            /* Check if the view is defined disposable. default is no */
            $disposable = soGetAsType($Item->getItem(DZS_DISPOSE), "bool");

            soDebug("dzEvent->handleSubariEventItem: Open new sub view: ".
                    $form_src, SOD_DET);
            /* Add dataxi view as sub view */
            $view_data = new dzViewData(DZ_VIEW_TYPE_DATAXI,
                                        $disposable, $form_src);
            /* Save the view data for the next state where
               the new form will be created */
            $SesData->Context = $view_data;
            $result->Status = DZE_OK;
            $result->NextState = DZ_STATE_INSERT_FORM;
            break;

        case DZMT_EVAL:

            $split = soSplitStr($split[1], ":", 1);
            $split[0] = str_replace("~", dzGetMainScriptPath(), $split[0]);
            $f = "include_once(\"".$split[0]."\"); \$result = ".
                               $split[1]."(\$ArraySet);";

            $result = "";
            eval($f);

            return $result;
            break;

        case DZMT_EXT_WINDOW:

            /* Prepare result */
            $result->Status = DZE_OK;
            $result->NextState = DZ_STATE_RECOVER_ERROR;

            /* Split into elements: [0]=target, [1]=store to send, 
             * [2...] optional parameters to external window, such as
             * width, height, scrollbar etc. */
            $elems = soExplode($action->Stream, ",");
            /* Two elements at minimum are required, otherwise STOP */
            if (count($elems) < 2) {
                soDebug("dzEvent/handleSubariEventItem: ".
                        "ERROR! Not enough parameters '".$action->Stream."'",
                        SOD_DET);
                break; // <-- EXIT CASE !!!
            }; // if

            /* Get action & store & recude array to parameters only */
            $action->Stream = $elems[0];
            $store_name = soCaseConv($elems[1], "U");
            for ($i = 0; $i < 2; $i++) {
                soDelElement($elems, 0);
            };

            $type = $SesData->HotView->Template->getViewData(DZ_VI_TYPE);

            /* Other than 'dialog' requires extra processing */
            if ($type != DZ_VIEW_TYPE_DIALOG) {
                /* Encode list/store to an url string */
                if ($store_name == "LIST") {
                    $list = $SesData->HotView->Laituri->getBrowseList();
                    if (soGetClass($list) == "soarrayset") {
                        $url_list = "";
                        $keys = $list->getKeys();
                        foreach ($keys as $key) {
                            $values = implode(SO_URL_ARRAY_DELIM,
                                              $list->getItem($key));
                            $values = urlencode($values);
                            $key = urlencode(str_replace(".", "/", $key));
                            $url_list = soJoinStr($url_list, "&",
                                                  "$key=$values", 1);
                        }; // foreach key

                        $action->Stream .= "?dzList=".$url_list;
                    }; // if
                } else {
                    $store = $SesData->HotView->Laituri->getStore($store_name);

                    /* Replace periods in the column names with DZ_DR_STR.
                     * Periods are considered operators in php.  */
                    $tmp_store = unserialize(serialize($store));
                    dzDotSubstitution($tmp_store, "to");
                    if (!soIsNull($tmp_store)) {
                        $action->Stream .= "?".$tmp_store->encode();
                    }; // if
                }; // else if
                $action->Stream .= "&".DZRI_SESSION."=".
                                   $SesData->BasicInfo->Id."&".
                                   DZRI_USER."=".
                                   $SesData->BasicInfo->UserID;
            } // if
            soInsElement($elems, $action->Stream, 0);
            soDebug("dzEvent/handleSubariEventItem: ".
                    "Open new window with url: ".$action->Stream, SOD_DET);

            $SesData->HotView->Template->addInitAction(DZIA_OPEN_NEW_WINDOW,
                                                       $elems);
            break;

        case "info":
            $html = $action->Stream;

            /* Add dataxi view as sub view */
            $view_data = new dzViewData(DZ_VIEW_TYPE_DIALOG,
                                        true, $html);
             /* Save the view data for the next state where
                the new form will be created */
            $SesData->Context = $view_data;
            $result->Status = DZE_OK;
            $result->NextState = DZ_STATE_INSERT_FORM;
            break;

            case "rpc":
            $rpc_def = $action->Stream;
            /* Call the remote procedure */
            if (!doSubariRpc($rpc_def, $SesData)) {
                $e_msg = new dzErrorMsg(DZER_RPC_SUBARI_FAILED, "Subari",
                                        DZERT_SYSTEM, DZERL_ERROR);
                $SesData->ErrorLog->add($e_msg);
            } // if
            $result->Status = DZE_OK;
            $result->NextState = DZ_STATE_RECOVER_ERROR;
            break;

        default:
            $result->Status = DZE_ERROR;
            $result->NextState = DZ_STATE_GO_INITIAL;
    } // switch

    return $result;
} // handleSubariEventItem


/** Calls a remote procedure
 *  @param string $Function The rpc definition e.g. "nakki($tiski,47)"
 *  @param dzSession $SesData Current session data
 *  @return bool True or false in case of error
 */
function doSubariRpc($Function, &$SesData) {
    /* Call remote function */
    $result_itu = dzRpcCall($Function, $SesData);

    if (!soIsNull($result_itu)) {
        $rpc_result = $result_itu->getBlockItemAt(DZI_CONTROL,
                                                  DZK_RESULT, 0);
    } else {
        $rpc_result = DZR_ERROR;
    } // if

    if ($rpc_result == DZR_OK) {
        soDebug("dzEvent/doSubariRpc: Rpc OK.", SOD_HI);
        /* Handle the result. */
        $data = $result_itu->getBlock(DZI_DATA);
        $SesData->HotView->Laituri->joinItu($data);
        $result = true;
    } else {
        soDebug("dzEvent/doSubariRpc: Rpc failed!", SOD_HI_E);
        $result = false;
    } // if $result

    return $result;
} // doSubariRpc

?>
